﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using fess.Maps;
using Microsoft.Xna.Framework;
using fess.Graphics;

namespace fess.RPG
{
  class Explosion : IActive
  {
    const float SpawnDelay = 0.15f;

    GenericMap screen;
    float power;
    ActionCharacter maker;
    TimeSpan start;
    Vector2 center;

    public Explosion(Vector2 place, float power, ActionCharacter maker, GenericMap map)
    {
      this.screen = map;
      this.power = power;
      this.maker = maker;
      this.center = place;

      map.drawables.Add(new FX(FXResources.fire1, place, 0 * (float)(Math.PI * 2 * Misc.Rand.NextDouble()), 1, map.game.time));
      for (int i = 0; i < 7; ++i)
      {
        float angle = Misc.RandAngle();
        map.drawables.Add(new BloodSplatter(FXResources.blood, place +
          Misc.ModArg((float)Misc.Rand.NextDouble() * 30, angle),
          Vector2.Zero,
          map.game.time + TimeSpan.FromSeconds(i * 0.1), map.passMap, Color.FromNonPremultiplied(0, 0, 0, 50), false, 1 / 1.3f));
      }

      map.MassDamage(place, power * 5 + 5, maker, (int)power);
      start = map.game.time;
    }

    public bool Update(TimeSpan time)
    {
      if ((time - start).TotalSeconds < SpawnDelay)
        return true;

      for (int i = 0; i < power / 3; ++i)
      {
        float angle = Misc.RandAngle();
        Vector2 shift = Misc.ModArg((float)(Misc.Rand.NextDouble() * 10), angle);
        screen.activities.Add(new Projectile(center + shift, shift, power / 2, false, maker, screen));
      }

      return false;
    }
  }

  class Projectile : IActive
  {
    const float Speed = 0.25f, SpawnPause = 0.005f;

    GenericMap map;
    float power;
    ActionCharacter maker;

    Vector2 flyFrom, direction, lastPos;
    TimeSpan start, lastSpawn;
    float lifetime;
    bool explode;

    public Projectile(Vector2 flyFrom, Vector2 direction, float power, bool explode, ActionCharacter maker, GenericMap map)
    {
      this.map = map;
      this.power = power;
      this.maker = maker;
      this.flyFrom = flyFrom;
      this.direction = direction / direction.Length();
      this.explode = explode;
      start = map.game.time;
      lastSpawn = start;
      lastPos = flyFrom;
      lifetime = power / 7;

      map.drawables.Add(new FX(FXResources.fire2, lastPos, Misc.RandAngle(), explode ? 0.1f : 0.05f, map.game.time, Color.White));
    }

    public bool Update(TimeSpan time)
    {
      float t = (float)(time - start).TotalSeconds / lifetime;
      if (t > 1)
        return false;

      Vector2 pos = flyFrom + direction * (float)(time - start).TotalMilliseconds * Speed;
      var newPos = map.MoveObject(lastPos, pos, 10);
      if (pos != lastPos && newPos == lastPos)
      {
        if (explode)
          map.activities.Add(new Explosion(lastPos, power, maker, map));
        else
          map.MassDamage(lastPos + direction * 10, power * 5, maker, (int)power);
        return false;
      }

      lastPos = newPos;
      if ((time - lastSpawn).TotalSeconds > SpawnPause)
      {
        map.drawables.Add(new FX(FXResources.fire2, lastPos, Misc.RandAngle(), explode ? 0.1f : 0.05f, time,
          Color.FromNonPremultiplied(255, 255, 255, (int)(255 * (1 - t)))));
        lastSpawn = time;
      }

      return true;
    }
  }
}
